/**
* @File: bleota_example.c
* @Version: V1.0
* @Author: rudius
* @Brief: OTA 模块测试示例 - 基于 MSH 命令
* @Logs:
* 	Date		Author		Notes
* 	2025-07-04	rudius		first version
*/

// <<< Use Configuration Wizard in Context Menu >>>

/* Private includes --------------------------------------------------------- */
#include "bleota.h"
#include <rtthread.h>
#include <stdlib.h>
#include <string.h>
#include "w25qxx.h"
#include "mx01.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Private config ----------------------------------------------------------- */
#define TEST_FIRMWARE_SIZE 1024  // 测试固件大小
#define BOOTLOADER_ADDRESS  0x08000000  // 假设的Bootloader地址

/* Private defines ---------------------------------------------------------- */
static uint8_t test_firmware[TEST_FIRMWARE_SIZE];  // 测试固件数据

/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static struct rym_ctx test_rym_ctx;
static rt_device_t test_rym_device = RT_NULL;
static ota_context_t test_ota_ctx;
/* Private function prototypes ---------------------------------------------- */
static void simulate_ymodem_transfer(void);
static void test_bootloader_jump(void);

/*----------------------------------------------------------------------------*/
/* Private functions -------------------------------------------------------- */

/**
 * @brief 模拟 Ymodem 传输
 */
static void simulate_ymodem_transfer(void)
{
    // 1. 生成测试固件
    for (int i = 0; i < TEST_FIRMWARE_SIZE; i++) {
        test_firmware[i] = i & 0xFF;
    }
    
    rt_kprintf("Generating test firmware (%d bytes)... OK\n", TEST_FIRMWARE_SIZE);
    
    // 2. 模拟文件头传输
    char header[128];
    rt_sprintf(header, "test.bin %d", TEST_FIRMWARE_SIZE);
    ota_rym_begin_cb(&test_rym_ctx, (rt_uint8_t *)header, strlen(header));
    rt_kprintf("File header: %s\n", header);
    
    // 3. 模拟数据传输
    int packets = (TEST_FIRMWARE_SIZE + 1023) / 1024;
    for (int i = 0; i < packets; i++) {
        int size = (i == packets - 1) ? 
                  TEST_FIRMWARE_SIZE - i * 1024 : 1024;
        
        ota_rym_data_cb(&test_rym_ctx, 
                        test_firmware + i * 1024, 
                        size);
        
        rt_kprintf("Sent packet %d/%d (%d bytes)\n", i + 1, packets, size);
        rt_thread_mdelay(50);
    }
    
    // 4. 模拟传输结束
    ota_rym_end_cb(&test_rym_ctx, RT_NULL, 0);
    rt_kprintf("Transfer complete!\n");
}

/**
 * @brief 测试 Bootloader 跳转（模拟）
 */
static void test_bootloader_jump(void)
{
    rt_kprintf("Preparing to jump to Bootloader...\n");
    rt_kprintf("This is a simulation, actual jump would reset device\n");
    
    // 模拟 Bootloader 参数
    uint32_t firmware_addr = test_ota_ctx.config.flash_base_addr;
    uint32_t firmware_size = test_ota_ctx.metadata.size;
    
    rt_kprintf("Bootloader address: 0x%08X\n", BOOTLOADER_ADDRESS);
    rt_kprintf("Firmware address: 0x%08X\n", firmware_addr);
    rt_kprintf("Firmware size: %d bytes\n", firmware_size);
    
    // 在实际系统中，此处会跳转到 Bootloader
    // 这里仅模拟
    rt_kprintf("Device would now reboot into Bootloader mode\n");
}

/* Public functions --------------------------------------------------------- */

/**
 * @brief 初始化测试环境
 */
static void ota_test_env_init(void)
{
    // 初始化测试固件
    memset(test_firmware, 0, sizeof(test_firmware));
    
    // 初始化 RYM 上下文
    memset(&test_rym_ctx, 0, sizeof(test_rym_ctx));
    
    rt_kprintf("OTA test environment initialized\n");
}

/**
 * @brief 测试 OTA 初始化
 */
static void ota_test_init(int argc, char **argv)
{
    // 测试正常初始化
    ota_config_t config = {
        .flash_base_addr = 0x00000000,
        .flash_max_size = 512 * 1024,
        .buffer_size = 2048,
        .auto_reboot = 0,
        .verify_crc = 1,
        .verify_md5 = 1
    };
    
    if (ota_init(&config) == RT_EOK) {
        rt_kprintf("ota_init() success\n");
    } else {
        rt_kprintf("ota_init() failed\n");
    }
}

/**
 * @brief 测试 OTA 启动
 */
static void ota_test_start(int argc, char **argv)
{
    ota_source_t source = OTA_SOURCE_CLI;
    
    if (argc > 1 && strcmp(argv[1], "ble") == 0) {
        rt_kprintf("Starting BLE OTA...\n");
        source = OTA_SOURCE_BLE;
    } else {
        rt_kprintf("Starting CLI OTA...\n");
    }
    
    if (ota_start(source) == RT_EOK) {
        rt_kprintf("ota_start() success\n");
    } else {
        rt_kprintf("ota_start() failed\n");
    }
}

/**
 * @brief 测试 OTA 中止
 */
static void ota_test_abort(int argc, char **argv)
{
    ota_abort();
    rt_kprintf("OTA aborted\n");
}

/**
 * @brief 测试 Flash 写入
 */
static void ota_test_write(int argc, char **argv)
{
    uint32_t addr = 0x00000000;
    uint8_t data[256];
    
    if (argc > 1) {
        addr = strtoul(argv[1], NULL, 16);
    }
    
    // 生成测试数据
    for (int i = 0; i < sizeof(data); i++) {
        data[i] = i & 0xFF;
    }
    
    // 写入 Flash
    w25qxx_page_program(test_ota_ctx.flash_dev, addr, data, sizeof(data));
    rt_kprintf("Wrote %d bytes to 0x%08X\n", sizeof(data), addr);
}

/**
 * @brief 测试进度计算
 */
static void ota_test_progress(int argc, char **argv)
{
    // 设置测试数据
    test_ota_ctx.metadata.size = 1000;
    
    if (argc > 1) {
        test_ota_ctx.bytes_written = atoi(argv[1]);
    } else {
        test_ota_ctx.bytes_written = 500;
    }
    
    rt_kprintf("Progress: %d%% (written: %d, total: %d)\n",
              ota_get_progress(),
              test_ota_ctx.bytes_written,
              test_ota_ctx.metadata.size);
}

/**
 * @brief 测试完整 OTA 流程
 */
static void ota_test_full(int argc, char **argv)
{
    // 初始化测试环境
    ota_test_env_init();
    
    // 准备测试配置
    ota_config_t config = {
        .flash_base_addr = 0x00000000,
        .flash_max_size = 512 * 1024,
        .buffer_size = 2048,
        .auto_reboot = 0,
        .verify_crc = 1,
        .verify_md5 = 1
    };
    
    // 1. 初始化 OTA
    if (ota_init(&config) != RT_EOK) {
        rt_kprintf("OTA init failed\n");
        return;
    }
    
    // 2. 启动 OTA (CLI 模式)
    if (ota_start(OTA_SOURCE_CLI) != RT_EOK) {
        rt_kprintf("OTA start failed\n");
        return;
    }
    
    // 3. 模拟 Ymodem 传输
    rt_kprintf("Simulating Ymodem transfer...\n");
    simulate_ymodem_transfer();
    
    // 4. 检查状态
    if (test_ota_ctx.state == OTA_STATE_READY) {
        rt_kprintf("OTA ready for upgrade!\n");
    } else {
        rt_kprintf("OTA failed, state: %d\n", test_ota_ctx.state);
    }
    
    // 5. 模拟跳转到 Bootloader
    rt_kprintf("Testing bootloader jump...\n");
    test_bootloader_jump();
}

/**
 * @brief 显示 OTA 状态
 */
static void ota_test_status(int argc, char **argv)
{
    rt_kprintf("OTA State: ");
    switch (test_ota_ctx.state) {
        case OTA_STATE_IDLE: rt_kprintf("Idle\n"); break;
        case OTA_STATE_RECEIVING: rt_kprintf("Receiving\n"); break;
        case OTA_STATE_VALIDATING: rt_kprintf("Validating\n"); break;
        case OTA_STATE_READY: rt_kprintf("Ready\n"); break;
        case OTA_STATE_FAILED: rt_kprintf("Failed\n"); break;
        default: rt_kprintf("Unknown (%d)\n", test_ota_ctx.state);
    }
    
    rt_kprintf("Progress: %d%%\n", ota_get_progress());
    rt_kprintf("Bytes written: %d\n", test_ota_ctx.bytes_written);
    rt_kprintf("Metadata size: %d\n", test_ota_ctx.metadata.size);
}

/********************** MSH 命令注册 **********************/
#ifdef RT_USING_FINSH
#include <finsh.h>

// 测试命令列表
// MSH_CMD_EXPORT(ota_test_init, Initialize OTA test environment);
// MSH_CMD_EXPORT(ota_test_start, Start OTA test [ble/cli]);
// MSH_CMD_EXPORT(ota_test_abort, Abort OTA test);
// MSH_CMD_EXPORT(ota_test_write, Test flash write [address]);
// MSH_CMD_EXPORT(ota_test_progress, Test progress calculation [written]);
// MSH_CMD_EXPORT(ota_test_full, Run full OTA test workflow);
// MSH_CMD_EXPORT(ota_test_status, Show OTA test status);

#endif /* RT_USING_FINSH */

#ifdef __cplusplus
}
#endif
// <<< end of configuration section >>>
/* ----------------------------- end of bleota_example.c ---------------------------- */